﻿using System;
using System.Collections;
namespace JoinBoxCurrency
{
    /// <summary>
    /// 基础类型
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    public class NotDuplicated<T1, T2>
    {
        public T1 T1Value { set; get; }
        public T2 T2Value { set; get; }
        public NotDuplicated(T1 t1Value, T2 t2Value)
        {
            T1Value = t1Value;
            T2Value = t2Value;
        }
    }

    /// <summary>
    /// 一个仿List的,但是加入重复数据无效不报错的容器
    /// </summary> 
    public class ListNot<T1, T2> : IEnumerable
    {
        //容器  
        private NotDuplicated<T1, T2>[] arr_NoRepetition = new NotDuplicated<T1, T2>[0];
        public T1[] T1Values
        {
            get
            {
                var ls = new T1[Count];
                for (int i = 0; i < Count; i++)
                {
                    ls[i] = arr_NoRepetition[i].T1Value;
                }
                return ls;
            }
        }
        public T2[] T2Values
        {
            get
            {
                var ls = new T2[Count];
                for (int i = 0; i < Count; i++)
                {
                    ls[i] = arr_NoRepetition[i].T2Value;
                }
                return ls;
            }
        }
        //容量
        public int Capacity
        {
            get
            {
                return arr_NoRepetition.Length;
            }
        }
        //元素总个数,但是数组会比这里长,这里是赋值的之后的
        public int Count { get; private set; } = 0;
        //添加元素 
        public void Add(NotDuplicated<T1, T2> notDuplicated)
        {
            //不加入已有重复元素的
            for (int i = 0; i < Count; i++)
            {
                var t1a = arr_NoRepetition[i].T1Value;
                var t2a = arr_NoRepetition[i].T2Value;
                if (t1a != null &&
                    t1a.Equals(notDuplicated.T1Value) &&
                    t2a != null &&
                    t2a.Equals(notDuplicated.T2Value)
                    )
                {
                    return;//如果键值对都一样就什么都不干
                }
            }
            //如果容量不够用
            if (Count == Capacity)
            {
                int arr;
                if (Capacity == 0)
                {
                    arr = 16;
                }
                else if (Capacity < 1000)
                {
                    arr = Capacity * 2;
                }
                else
                {
                    arr = Capacity + 100;
                }
                //创建新数组
                var arrNew_NoRepetition = new NotDuplicated<T1, T2>[arr];
                //复制元素给新数组
                arr_NoRepetition.CopyTo(arrNew_NoRepetition, 0);
                //替换引用
                arr_NoRepetition = arrNew_NoRepetition;
            }
            //添加元素
            int co = Count++;
            arr_NoRepetition[co] = notDuplicated;
        }
        //添加元素
        public void Add(T1 t1value, T2 t2value)
        {
            Add(new NotDuplicated<T1, T2>(t1value, t2value));
        }
        //从指定位置移除
        public void RemoveAt(int index)
        {
            //如果越界
            if (index >= Count)
            {
                throw new IndexOutOfRangeException();
            }
            else
            {
                //元素前移
                for (int i = index; i <= Count - 2; i++)
                {
                    arr_NoRepetition[i] = arr_NoRepetition[i + 1];
                }
                Count--;//总数减少
            }
        }
        /// <summary>
        /// 是否包含键
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(NotDuplicated<T1, T2> item)
        {
            for (int i = 0; i < Count; i++)
            {
                if (arr_NoRepetition[i].Equals(item))//找到
                {
                    return true;
                }
            }
            return false;//未找到
        }
        //索引器
        public NotDuplicated<T1, T2> this[int index]
        {
            get //例如 int a=arr[i]
            {
                //如果索引超出范围,抛出异常
                if (index >= Count)
                {
                    throw new IndexOutOfRangeException();
                    //throw new ArgumentException("索引超出范围");
                }
                else
                {
                    return arr_NoRepetition[index];
                }
            }
            set //例如 arr[i]=5;
            {
                //如果索引超出范围,抛出异常
                if (index >= Count)
                {
                    throw new IndexOutOfRangeException();
                }
                else
                {
                    arr_NoRepetition[index] = value;
                }
            }
        }
        //迭代,支持foreach,支持var识别
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        //这里控制了foreach的var自动属性..令人疑惑不是强制的...估计的反射函数名,有则调用
        public ListNoRepetitionEnum<T1, T2> GetEnumerator()
        {
            //去掉多余的空值
            var ls = new NotDuplicated<T1, T2>[Count];
            for (int i = 0; i < Count; i++)
            {
                ls[i] = arr_NoRepetition[i];
            }
            return new ListNoRepetitionEnum<T1, T2>(ls);
        }
        /// <summary>
        /// 清空数组
        /// </summary>
        public void Clear()
        {
            arr_NoRepetition = new NotDuplicated<T1, T2>[0];
            Count = 0;
        }
    }
    public class ListNoRepetitionEnum<T1, T2> : IEnumerator
    {
        public NotDuplicated<T1, T2>[] _lnr;
        public ListNoRepetitionEnum(NotDuplicated<T1, T2>[] list)
        {
            _lnr = list;
        }
        //集合当前的元素
        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }
        public NotDuplicated<T1, T2> Current
        {
            get
            {
                try
                {
                    return _lnr[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
        //计数
        int position = -1;
        //迭代
        public bool MoveNext()
        {
            position++;
            return position < _lnr.Length;
        }
        //初始计数赋值
        public void Reset()
        {
            position = -1;
        }
    }
}
